fix(ai): accept a stringified query_workspace arg instead of crashing#1273
Merged
Conversation
The query_workspace tool schema declares `query` as an object, but some models/ providers serialize it as a JSON string (a known tool-calling quirk). _handle_query assumed a dict and passed it straight to _decrypt_dict, which did `d.items()` and raised `AttributeError: 'str' object has no attribute 'items'` — killing the action (only surfaced as a retry via safe_dispatch_action). Any model that stringifies the object arg could never use query_workspace. Coerce a stringified query back to a dict (json.loads) before decrypt/search, and return a clean, LLM-actionable Error for a genuinely malformed or non-dict query instead of crashing. Mirrors the existing add_finding scalar coercion. Also harden _decrypt_dict to no-op on non-dict input as a backstop. Tests: stringified query is coerced+searched (with encryptor active — the exact original crash condition), non-JSON string and non-dict return a clean Error, and _decrypt_dict returns non-dict input unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NNjPggRSVZ2xnLb7ZxWP5H
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug (hit during CLI testing)
The
query_workspacetool schema correctly declaresqueryastype: object, but the model returned it as a JSON string ('{"_type":"url","verified":true}') — a well-known tool-calling quirk where providers serialize nested object params as strings._handle_queryassumed a dict and handed it to_decrypt_dict, which doesd.items()→AttributeError. It's caught bysafe_dispatch_action(so non-fatal — the model retried withcurl), but it wastes an iteration and any model that stringifies object args can never usequery_workspace. (_decrypt_dictonly fires when the encryptor is active, i.e. the defaultsensitive=True.)Fix
_handle_query: ifqueryis astr,json.loadsit before decrypt/search. On a non-JSON string or a non-dict, return a clean, LLM-actionableError("query must be a JSON object …") instead of crashing. Mirrors the existingadd_findingscalar coercion._decrypt_dict: no-op backstop on non-dict input.Tests
TestHandleQuery: stringified query is coerced+searched with the encryptor active (the exact original crash condition); non-JSON string and non-dict each return one cleanError.TestDecryptDict: non-dict input returned unchanged. Full AI suite: no new failures vs branch baseline.Found while testing
ai-testing; targetsai-resiliency(#1241).🤖 Generated with Claude Code